package com.mmall.demo2.shiro;

import com.mmall.demo2.common.Const;
import com.mmall.demo2.common.serialize.ObjectMapper;
import com.mmall.demo2.common.response.Servlets;
import com.mmall.demo2.common.redis.RedisPoolUtil;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.Collection;

/**
 * @Author: jiaru
 * @Description: session 保存到 redis 的增删改查操作
 * @redis写入方式:   1. 写入：对象转换成byte —> 存入redis；
 *                  2. 取出: 获取byte数据 —> 序列化为java对象；
 * @Date: Created on 2018/10/25
 * @Modify:
 */
public class RedisSessionDao extends AbstractSessionDAO {

    /**
     * 创建session 信息
     * @param session 前端传来的 session 信息
     * @return
     */
    @Override
    protected Serializable doCreate(Session session) {
        // 创建唯一编号
        Serializable sessionId = this.generateSessionId(session);
        // 创建session
        this.assignSessionId(session, sessionId);
        // session 保存到redis缓存中
        this.update(session);
        // 返回session编号
        return sessionId;
    }

    /**
     * 读取 session 信息
     * @param sessionId 前端传来的 session 编号
     * @return
     */
    @Override
    protected Session doReadSession(Serializable sessionId) {
        /**** 如果 sessionId 为空，则直接返回 ****/
        if (sessionId == null) {
            return null;
        }
        /**** 从 request 中获取 session 信息 ****/
        Session session = null;
        // 获取 request 请求
        HttpServletRequest request = Servlets.getRequest();
        // 获取 session
        if (request != null) {
            session = (Session) request.getAttribute((String) sessionId);
        }
        // 如果 session 非空，直接返回 session
        if (session != null){
            return session;
        }

        /****  如果 sesssion 为空，则从redis中读取 ****/
        // 获取的键名称
        byte[] sessionKey = ObjectMapper.getBytes((String) sessionId);
        // 从 redis 中取出的 byte[] 数据
        byte[] sessionByte = RedisPoolUtil.get(sessionKey);
        // redis 中的 byte[] 转换 Java 对象
        session = (Session) ObjectMapper.toObject(sessionByte);
        return session;
    }

    /**
     * 更新redis中的 session 信息
     * @param session 前端传来的 session 信息
     * @throws UnknownSessionException
     */
    @Override
    public void update(Session session) throws UnknownSessionException {
        if (session == null) {
            return;
        }
        // 设置 session 过期时间
        session.setTimeout(30 * 60 * 1000);
        // session 信息
        byte[] sessionId = ObjectMapper.getBytes((String) session.getId());
        byte[] sessionVal = ObjectMapper.toBytes(session);
        // 保存 session 到 redis 中
        RedisPoolUtil.setEx(sessionId, sessionVal, Const.RedisCacheExTime.REDIS_SESSION_EXTIME);
    }


    /**
     * 删除 session
     * @param session 前端传来的 session 信息
     */
    @Override
    public void delete(Session session) {
        if (session == null) {
            return;
        }
        byte[] sessionId = ObjectMapper.getBytes((String)session.getId());
        RedisPoolUtil.del(sessionId);
    }

    /**
     * 获取在线用户
     * @return
     */
    @Override
    public Collection<Session> getActiveSessions() {
        return null;
    }
}
